<?php
	
	namespace Aspic\Form\Element;
	
	use Aspic as A;
	use Aspic\Form as Form;
	use Aspic\Security\Security as S;
	
	/**
	* CheckBoxList form element
	*/
	class CheckBoxList extends AbstractStandardElement {
		
		protected $checkBoxes;
		protected $_columnsNumber;
		/**
		 *
		 * @var bool Define the order of displaying checkboxes : labels first or checkboxes first
		 */
		protected $_checkBoxesFirst;


	 public function __construct($name, $label, array $checkBoxes = array(), array $options = array(), array $attributes = array(), array $validations = array()) {
			parent::__construct($name, $label, $options, $attributes, $validations);
			
			$this->setCheckBoxes($checkBoxes);
			$this->opt('columnsNumber', 4, true);
			$this->opt('checkBoxesFirst', false, true); // Labels first
		}
		
		public function setCheckBoxes(array $checkBoxes) {
			foreach($checkBoxes as $item) {
				$item = array_merge(
					array(
						'label' => '',
						'value' => '',
						'checked' => null,
						'attributes' => array(), 
					),
					$item
				);
				
				$this->addCheckBox($item['label'], $item['value'], $item['checked'], $item['attributes']);
			}
		}
		
		public function addCheckBox($label, $value, $checked = false, array $attributes = array()) {
			if(!$checked)
				$checked = null;
			
			if (!isset($attributes['id'])) {
				$attributes['id'] = $this->getCheckBoxId($value);
			}
			$this->checkBoxes[] = array(
				'label' => $label,
				'attributes' => array_merge( 
					$attributes, 
					array(
						'value' => $value, 
						'checked' => $checked
					)
				)
			);
		}
		
		/**
		* Set checkboxes from a 1-dimension array like: array('value1' => 'label1', 'value2' => 'label2')
		*/
		public function setKeyValueCheckboxes($items) {
			$parsedItems = array();
			
			foreach($items as $value => $label) {
				$item = array();
				
				$item['value'] = $value;
				$item['label'] = $label;
				
				$parsedItems[] = $item;
			}

			return $this->setCheckBoxes($parsedItems);
		}
		
		/**
		 * Check given checkboxes values
		 * @param array $values 
		 */
		public function setCheckedValues(array $values) {
			foreach ($this->checkBoxes as &$cb) {
				if (in_array($cb['attributes']['value'], $values)) {
					$cb['attributes']['checked'] = 'checked';
				}
				else {
					$cb['attributes']['checked'] = null;
				}
			}
			
		}
		
		public function outLabel() {
			$out = '<label class="'.$this->opt('labelClass').'">'.S::escapeXss($this->opt('labelText')).'</label>';
			
			return $out;
		}
		
		public function outInput() {
			$cb = new A\CodeBuilder;
			$colNumber = $this->opt('columnsNumber');
			
			$cb->next('<span '.$this->getAttrsStr().'>');
			
			$i = 0;
			
			if(count($this->checkBoxes)) {
				foreach ($this->checkBoxes as $checkBox) {
					$label = $checkBox['label'];
					$attributes = $checkBox['attributes'];

					$checkBoxHtml = '<input'.A\UString::implodeHtmlAttributes($attributes, true).' type="checkbox" name="'.$this->getName(true).'[]" />';
					$labelHtml = '<label for="'.S::escapeSpecialChars($attributes['id']).'">'.S::escape($label).'</label>';

					$cb->nl('<span>');

					if ($this->opt('checkBoxesFirst')) {
						$cb->nl($checkBoxHtml);
						$cb->next($labelHtml);
					}
					else {
						$cb->nl($labelHtml);
						$cb->next($checkBoxHtml);
					}

					$cb->nl('</span>');

					if($colNumber AND ($i % $colNumber == 0)) {
						$cb->nl('<br />');
					}

					$i++;
				}
			}
			
			$cb->next('</span>');
			
			return $cb->out();
		}
		
		public function getCheckBoxId($checkBoxValue) {
			return $this->attr('id').'_cb_'.$checkBoxValue;
		}
		
		public function getDefaultId() {
			return 'cbList'.ucfirst($this->getName());
		}
		
		public function bind(array $formData = null) {
			if(($value = $this->getValue($formData)) AND is_array($value)) { // is_array here because must be an array
				$this->setCheckedValues($value);
			}
		}
		
	}
	
?>